home *** CD-ROM | disk | FTP | other *** search
/ Freelog 115 / FreelogNo115-MaiJuin2013.iso / Internet / Filezilla Server / FileZilla_Server-0_9_41.exe / source / Server.cpp < prev    next >
C/C++ Source or Header  |  2011-11-06  |  43KB  |  1,470 lines

  1. // FileZilla Server - a Windows ftp server
  2.  
  3. // Copyright (C) 2002-2004 - Tim Kosse <tim.kosse@gmx.de>
  4.  
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the GNU General Public License
  7. // as published by the Free Software Foundation; either version 2
  8. // of the License, or (at your option) any later version.
  9.  
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. // GNU General Public License for more details.
  14.  
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program; if not, write to the Free Software
  17. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. // Server.cpp: Implementierung der Klasse CServer.
  20. //
  21. //////////////////////////////////////////////////////////////////////
  22.  
  23. #include "stdafx.h"
  24. #include "Server.h"
  25. #include "Options.h"
  26. #include "ServerThread.h"
  27. #include "ListenSocket.h"
  28. #include "AdminListenSocket.h"
  29. #include "AdminInterface.h"
  30. #include "AdminSocket.h"
  31. #include "Permissions.h"
  32. #include "FileLogger.h"
  33. #include "version.h"
  34. #include "defs.h"
  35. #include "iputils.h"
  36. #include "autobanmanager.h"
  37.  
  38. #ifndef MB_SERVICE_NOTIFICATION
  39. #define MB_SERVICE_NOTIFICATION          0x00040000L
  40. #endif
  41.  
  42. //////////////////////////////////////////////////////////////////////
  43. // Konstruktion/Destruktion
  44. //////////////////////////////////////////////////////////////////////
  45.  
  46. CServer::CServer()
  47. {
  48.     m_hWnd=0;
  49.     m_pOptions = NULL;
  50.     m_pAdminInterface = new CAdminInterface(this);
  51.     m_nServerState = 0;
  52.     m_bQuit = FALSE;
  53.  
  54.     m_nSendCount = m_nRecvCount = 0;
  55.     m_nTimerID = 0;
  56.     m_nBanTimerID = 0;
  57.  
  58.     // Since this thread has to handle notifications, increase it's priority
  59.     SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
  60.  
  61.     m_pAutoBanManager = 0;
  62. }
  63.  
  64. CServer::~CServer()
  65. {
  66.     for (std::list<CListenSocket*>::iterator iter = m_ListenSocketList.begin(); iter != m_ListenSocketList.end(); iter++)
  67.         delete *iter;
  68.     m_ListenSocketList.clear();
  69.     
  70.     for (std::list<CAdminListenSocket*>::iterator adminIter = m_AdminListenSocketList.begin(); adminIter != m_AdminListenSocketList.end(); adminIter++)
  71.         delete *adminIter;
  72.     m_AdminListenSocketList.clear();
  73.  
  74.     delete m_pAdminInterface;
  75.  
  76.     delete m_pAutoBanManager;
  77.     delete m_pFileLogger;
  78.     delete m_pOptions;
  79.  
  80.     //Destroy window
  81.     if (m_hWnd)
  82.     {
  83.         hMainWnd = 0;
  84.         DestroyWindow(m_hWnd);
  85.         m_hWnd = 0;
  86.     }
  87. }
  88.  
  89. bool CServer::Create()
  90. {
  91.     //Create window
  92.     WNDCLASSEX wndclass; 
  93.     wndclass.cbSize=sizeof wndclass; 
  94.     wndclass.style=0; 
  95.     wndclass.lpfnWndProc=WindowProc; 
  96.     wndclass.cbClsExtra=0; 
  97.     wndclass.cbWndExtra=0; 
  98.     wndclass.hInstance=GetModuleHandle(0); 
  99.     wndclass.hIcon=0; 
  100.     wndclass.hCursor=0; 
  101.     wndclass.hbrBackground=0; 
  102.     wndclass.lpszMenuName=0; 
  103.     wndclass.lpszClassName=_T("FileZilla Server Helper Window"); 
  104.     wndclass.hIconSm=0; 
  105.     
  106.     RegisterClassEx(&wndclass);
  107.     
  108.     m_hWnd = CreateWindow(_T("FileZilla Server Helper Window"), _T("FileZilla Server Helper Window"), 0, 0, 0, 0, 0, 0, 0, 0, GetModuleHandle(0));
  109.     if (!m_hWnd)
  110.         return false;
  111.     SetWindowLongPtr(m_hWnd, GWLP_USERDATA, (LONG)this);
  112.  
  113.     hMainWnd = m_hWnd;
  114.  
  115.     m_pOptions = new COptions;
  116.     m_pFileLogger = new CFileLogger(m_pOptions);
  117.     m_pAutoBanManager = new CAutoBanManager(m_pOptions);
  118.     
  119.     //Create the threads
  120.     int num = (int)m_pOptions->GetOptionVal(OPTION_THREADNUM);
  121.     for (int i = 0; i < num; i++)
  122.     {
  123.         int index = GetNextThreadNotificationID();
  124.         CServerThread *pThread = new CServerThread(WM_FILEZILLA_SERVERMSG + index);
  125.         m_ThreadNotificationIDs[index] = pThread;
  126.         if (pThread->Create(THREAD_PRIORITY_NORMAL, CREATE_SUSPENDED))
  127.         {
  128.             pThread->ResumeThread();
  129.             m_ThreadArray.push_back(pThread);
  130.         }
  131.     }
  132.     
  133.     m_pFileLogger->Log(GetVersionString() + _T(" started"));
  134.     m_pFileLogger->Log(_T("Initializing Server."));
  135.  
  136.     m_nTimerID = SetTimer(m_hWnd, 1234, 10000, NULL);
  137.     ASSERT(m_nTimerID);
  138.  
  139.     m_nBanTimerID = SetTimer(m_hWnd, 1235, 60000, NULL);
  140.     ASSERT(m_nBanTimerID);
  141.  
  142.     if (CreateListenSocket())
  143.     {
  144.         m_nServerState = STATE_ONLINE;
  145.         ShowStatus(_T("Server online."), 0);
  146.     }
  147.     else
  148.         ShowStatus(_T("Server not online."), 1);
  149.  
  150.     CreateAdminListenSocket();
  151.  
  152.     return true;
  153. }
  154.  
  155. HWND CServer::GetHwnd()
  156. {
  157.     return m_hWnd;
  158. }
  159.  
  160. LRESULT CALLBACK CServer::WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  161. {
  162.     CServer *pServer=(CServer *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
  163.  
  164.     if (message == WM_CLOSE)
  165.     {
  166.         pServer->OnClose();
  167.         return 0;
  168.     }
  169.     else if (hWnd && message == WM_DESTROY)
  170.     {
  171.         ASSERT( hWnd == pServer->m_hWnd);
  172.         HANDLE *handle = new HANDLE[pServer->m_ThreadArray.size()];
  173.         unsigned int i = 0;
  174.         std::list<CServerThread *>::iterator iter;
  175.         for (iter = pServer->m_ThreadArray.begin(); iter != pServer->m_ThreadArray.end(); iter++, i++)
  176.         {
  177.             handle[i]=(*iter)->m_hThread;
  178.             (*iter)->PostThreadMessage(WM_QUIT, 0, 0);
  179.         }
  180.         for (i=0; i<pServer->m_ThreadArray.size(); i++)
  181.         {
  182.             int res=WaitForSingleObject(handle[i],INFINITE);
  183.             if (res==WAIT_FAILED)
  184.                 res=GetLastError();
  185.         }
  186.         delete [] handle;
  187.         handle = new HANDLE[pServer->m_ClosedThreads.size()];
  188.         i=0;
  189.         for (iter = pServer->m_ClosedThreads.begin(); iter != pServer->m_ClosedThreads.end(); iter++, i++)
  190.         {
  191.             handle[i]=(*iter)->m_hThread;
  192.             (*iter)->PostThreadMessage(WM_QUIT, 0, 0);
  193.         }
  194.         for (i = 0; i < pServer->m_ClosedThreads.size(); i++)
  195.         {
  196.             int res=WaitForSingleObject(handle[i],INFINITE);
  197.             if (res==WAIT_FAILED)
  198.                 res=GetLastError();
  199.         }
  200.         delete [] handle;
  201.         for (std::list<CAdminListenSocket*>::iterator iter2 = pServer->m_AdminListenSocketList.begin(); iter2!=pServer->m_AdminListenSocketList.end(); iter2++)
  202.         {
  203.             (*iter2)->Close();
  204.             delete *iter2;
  205.         }
  206.         pServer->m_AdminListenSocketList.clear();
  207.         delete pServer->m_pAdminInterface;
  208.         pServer->m_pAdminInterface = NULL;
  209.         delete pServer->m_pOptions;
  210.         pServer->m_pOptions = NULL;
  211.         if (pServer->m_nTimerID)
  212.         {
  213.             KillTimer(pServer->m_hWnd, pServer->m_nTimerID);
  214.             pServer->m_nTimerID = 0;
  215.         }
  216.         PostQuitMessage(0);
  217.         return 0;
  218.     }
  219.     else if (message == WM_TIMER)
  220.         pServer->OnTimer(wParam);
  221.     else if (message == WM_FILEZILLA_RELOADCONFIG)
  222.     {
  223.         COptions options;
  224.         options.ReloadConfig();
  225.         CPermissions perm;
  226.         perm.ReloadConfig();
  227.     }
  228.     else if (message >= WM_FILEZILLA_SERVERMSG)
  229.     {
  230.         UINT index = message - WM_FILEZILLA_SERVERMSG;
  231.         if (index >= pServer->m_ThreadNotificationIDs.size())
  232.             return 0;
  233.  
  234.         CServerThread *pThread = pServer->m_ThreadNotificationIDs[index];
  235.         if (pThread)
  236.         {
  237.             std::list<CServerThread::t_Notification> notifications;
  238.             pThread->GetNotifications(notifications);
  239.             for (std::list<CServerThread::t_Notification>::const_iterator iter = notifications.begin(); iter != notifications.end(); iter++)
  240.                 if (pServer->OnServerMessage(pThread, iter->wParam, iter->lParam) != 0)
  241.                     break;
  242.         }
  243.         return 0;
  244.     }
  245.     
  246.     return ::DefWindowProc(hWnd, message, wParam, lParam);
  247. }
  248.  
  249. LRESULT CServer::OnServerMessage(CServerThread* pThread, WPARAM wParam, LPARAM lParam)
  250. {
  251.     if (wParam == FSM_STATUSMESSAGE)
  252.     {
  253.         t_statusmsg *msg = reinterpret_cast<t_statusmsg *>(lParam);
  254.         if (!msg)
  255.             return 0;
  256.  
  257.         CStdString str;
  258.  
  259.         FILETIME fFileTime;
  260.         SystemTimeToFileTime(&msg->time, &fFileTime);
  261.         
  262.         str.Format(_T("(%06d)- %s (%s)> %s"), msg->userid, (LPCTSTR)msg->user, (LPCTSTR)msg->ip, (LPCTSTR)msg->status);
  263.         ShowStatus(fFileTime.dwHighDateTime, fFileTime.dwLowDateTime, str, msg->type);
  264.         delete [] msg->status;
  265.         delete [] msg->user;
  266.         delete msg;
  267.     }
  268.     else if (wParam == FSM_CONNECTIONDATA)
  269.     {
  270.         t_connop *pConnOp = reinterpret_cast<t_connop*>(lParam);
  271.         if (!pConnOp)
  272.             return 0;
  273.         
  274.         int len;
  275.         unsigned char *buffer;
  276.  
  277.         switch (pConnOp->op)
  278.         {
  279.         case USERCONTROL_CONNOP_ADD:
  280.             {
  281.                 t_connectiondata_add* pData = (t_connectiondata_add*)pConnOp->data;
  282.                 t_connectiondata data;
  283.                 data.userid = pConnOp->userid;
  284.                 data.pThread = pThread;
  285.                 _tcsncpy(data.ip, pData->ip, 40);
  286.                 data.port = pData->port;
  287.                 data.transferMode = 0;
  288.                 data.currentOffset = 0;
  289.                 data.totalSize = -1;
  290.  
  291.                 m_UsersList[pConnOp->userid] = data;
  292.  
  293.                 char* utf8 = ConvToNetwork(pData->ip);
  294.                 int iplen = strlen(utf8);
  295.                 len = 2 + 4 + 2 + iplen + 4;
  296.                 buffer = new unsigned char[len];
  297.                 buffer[2 + 4] = iplen / 256;
  298.                 buffer[2 + 4 + 1] = iplen % 256;        
  299.                 memcpy(buffer + 2 + 4 + 2, utf8, iplen);
  300.                 delete [] utf8;
  301.                 memcpy(buffer + 2 + 4 + 2 + iplen, &pData->port, 4);
  302.  
  303.                 delete pData;
  304.             }
  305.             break;
  306.         case USERCONTROL_CONNOP_CHANGEUSER:
  307.             {
  308.                 t_connectiondata_changeuser* pData = (t_connectiondata_changeuser*)pConnOp->data;
  309.                 m_UsersList[pConnOp->userid].user = pData->user;
  310.             
  311.                 char* utf8 = ConvToNetwork(pData->user);
  312.                 if (!utf8)
  313.                 {
  314.                     buffer = new unsigned char[2 + 2 + 4 + 2];
  315.                     buffer[2 + 4] = 0;
  316.                     buffer[2 + 4 + 1] = 0;
  317.                     len = 8;
  318.                 }
  319.                 else
  320.                 {
  321.                     int userlen = strlen(utf8);
  322.                     len = 2 + 4 + 2 + userlen;
  323.                     buffer = new unsigned char[len];
  324.                     buffer[2 + 4] = userlen / 256;
  325.                     buffer[2 + 4 + 1] = userlen % 256;        
  326.                     memcpy(buffer + 2 + 4 + 2, utf8, userlen);
  327.                     delete [] utf8;
  328.                 }
  329.  
  330.                 delete pData;
  331.             }
  332.             break;
  333.         case USERCONTROL_CONNOP_REMOVE:
  334.             {
  335.                 std::map<int, t_connectiondata>::iterator iter = m_UsersList.find(pConnOp->userid);
  336.                 if (iter != m_UsersList.end())
  337.                     m_UsersList.erase(iter);
  338.  
  339.                 len = 6;
  340.                 buffer = new unsigned char[len];
  341.             }
  342.             break;
  343.         case USERCONTROL_CONNOP_TRANSFERINIT:
  344.             {
  345.                 t_connectiondata_transferinfo* pData = (t_connectiondata_transferinfo*)pConnOp->data;
  346.                 t_connectiondata& data = m_UsersList[pConnOp->userid];
  347.                 data.transferMode = pData->transferMode;
  348.                 data.physicalFile = pData->physicalFile;
  349.                 data.logicalFile = pData->logicalFile;
  350.                 data.currentOffset = pData->startOffset;
  351.                 data.totalSize = pData->totalSize;
  352.  
  353.                 if (data.transferMode)
  354.                 {
  355.                     char* physicalFile = ConvToNetwork(pData->physicalFile);
  356.                     int physicalFileLen = physicalFile ? strlen(physicalFile) : 0;
  357.                     char* logicalFile = ConvToNetwork(pData->logicalFile);
  358.                     int logicalFileLen = logicalFile ? strlen(logicalFile) : 0;
  359.                     len = 2 + 4 + 1 + 2 + physicalFileLen + 2 + logicalFileLen;
  360.                     if (data.currentOffset != 0)
  361.                         len += 8;
  362.                     if (data.totalSize != -1)
  363.                         len += 8;
  364.  
  365.                     buffer = new unsigned char[len];
  366.                     unsigned char *p = buffer + 6;
  367.                     *p = data.transferMode;
  368.                     
  369.                     // Bit 5 and 6 indicate presence of currentOffset and totalSize.
  370.                     if (data.currentOffset != 0)
  371.                         *p |= 0x20;
  372.                     if (data.totalSize != -1)
  373.                         *p |= 0x40;
  374.                     p++;
  375.                     
  376.                     *p++ = physicalFileLen / 256;
  377.                     *p++ = physicalFileLen % 256;        
  378.                     if (physicalFile)
  379.                     {
  380.                         memcpy(p, physicalFile, physicalFileLen);
  381.                         delete [] physicalFile;
  382.                     }
  383.                     p += physicalFileLen;
  384.  
  385.                     *p++ = logicalFileLen / 256;
  386.                     *p++ = logicalFileLen % 256;        
  387.                     if (logicalFile)
  388.                     {
  389.                         memcpy(p, logicalFile, logicalFileLen);
  390.                         delete [] logicalFile;
  391.                     }
  392.                     p += logicalFileLen;
  393.  
  394.                     if (data.currentOffset != 0)
  395.                     {
  396.                         memcpy(p, &data.currentOffset, 8);
  397.                         p += 8;
  398.                     }
  399.                     if (data.totalSize != -1)
  400.                     {
  401.                         memcpy(p, &data.totalSize, 8);
  402.                         p += 8;
  403.                     }
  404.                 }
  405.                 else
  406.                 {
  407.                     len = 2 + 4 + 1;
  408.                     buffer = new unsigned char[len];
  409.                     buffer[2 + 4] = 0;
  410.                 }
  411.                 delete pData;
  412.             }
  413.             break;
  414.         case USERCONTROL_CONNOP_TRANSFEROFFSETS:
  415.             {
  416.                 t_connectiondata_transferoffsets* pData = (t_connectiondata_transferoffsets*)pConnOp->data;
  417.                 buffer = pData->pData;
  418.                 len = pData->len;
  419.  
  420.                 unsigned char* p = buffer + 2;
  421.                 int* userid;
  422.                 __int64* offset;
  423.                 while ((p - buffer + 12) <= len)
  424.                 {
  425.                     userid = (int*)p;
  426.                     offset = (__int64*)(p + 4);
  427.                     t_connectiondata& data = m_UsersList[*userid];
  428.                     data.currentOffset = *offset;
  429.  
  430.                     p += 12;                    
  431.                 }
  432.                 delete pData;
  433.             }
  434.             break;
  435.         }
  436.         buffer[0] = USERCONTROL_CONNOP;
  437.         buffer[1] = pConnOp->op;
  438.         if (pConnOp->op != USERCONTROL_CONNOP_TRANSFEROFFSETS)
  439.             memcpy(buffer + 2, &pConnOp->userid, 4);
  440.         
  441.         m_pAdminInterface->SendCommand(2, 3, buffer, len);
  442.         delete [] buffer;
  443.         delete pConnOp;
  444.     }
  445.     else if (wParam == FSM_THREADCANQUIT)
  446.     {
  447.         std::list<CServerThread *>::iterator iter;
  448.         for (iter = m_ThreadArray.begin(); iter != m_ThreadArray.end(); iter++)
  449.         {
  450.             if (*iter == pThread)
  451.             {
  452.                 HANDLE handle=pThread->m_hThread;
  453.                 pThread->PostThreadMessage(WM_QUIT, 0, 0);
  454.                 int res=WaitForSingleObject(handle, INFINITE);
  455.                 if (res==WAIT_FAILED)
  456.                     res=GetLastError();
  457.                 m_ThreadArray.erase(iter);
  458.                 FreeThreadNotificationID(pThread);
  459.                 if (!m_ThreadArray.size() && !m_ClosedThreads.size())
  460.                 {
  461.                     m_nServerState &= ~(STATE_ONLINE | STATE_MASK_GOOFFLINE);
  462.                     SendState();
  463.                     if (!m_bQuit)
  464.                         ShowStatus(_T("Server offline."), 1);
  465.                     else
  466.                     {
  467.                         hMainWnd = 0;
  468.                         DestroyWindow(m_hWnd);
  469.                         m_hWnd = 0;
  470.                     }
  471.                 }
  472.                 return -1;
  473.             }
  474.         }
  475.         for (iter = m_ClosedThreads.begin(); iter != m_ClosedThreads.end(); iter++)
  476.         {
  477.             if (*iter == pThread)
  478.             {
  479.                 HANDLE handle = pThread->m_hThread;
  480.                 pThread->PostThreadMessage(WM_QUIT, 0, 0);
  481.                 int res = WaitForSingleObject(handle, INFINITE);
  482.                 if (res == WAIT_FAILED)
  483.                     res = GetLastError();
  484.                 m_ClosedThreads.erase(iter);
  485.                 FreeThreadNotificationID(pThread);
  486.                 if (!m_ThreadArray.size() && !m_ClosedThreads.size())
  487.                 {
  488.                     m_nServerState &= ~(STATE_ONLINE | STATE_MASK_GOOFFLINE);
  489.                     SendState();
  490.                     if (!m_bQuit)
  491.                         ShowStatus(_T("Server offline."), 1);
  492.                     else
  493.                     {
  494.                         hMainWnd = 0;
  495.                         DestroyWindow(m_hWnd);
  496.                         m_hWnd = 0;
  497.                     }
  498.                 }
  499.                 return -1;
  500.             }
  501.             
  502.         }
  503.     }
  504.     else if (wParam == FSM_SEND)
  505.     {
  506.         char buffer[5];
  507.         buffer[0] = 1;
  508.         memcpy(buffer+1, &lParam, 4);
  509.         m_pAdminInterface->SendCommand(2, 7, buffer, 5);
  510.         m_nSendCount += lParam;
  511.     }
  512.     else if (wParam == FSM_RECV)
  513.     {
  514.         char buffer[5];
  515.         buffer[0] = 0;
  516.         memcpy(buffer+1, &lParam, 4);
  517.         m_pAdminInterface->SendCommand(2, 7, buffer, 5);
  518.         m_nRecvCount += lParam;
  519.     }
  520.     return 0;
  521. }
  522.  
  523.  
  524. void CServer::OnClose()
  525. {
  526.     for (std::list<CListenSocket*>::iterator listIter = m_ListenSocketList.begin(); listIter != m_ListenSocketList.end(); listIter++)
  527.     {
  528.         (*listIter)->Close();
  529.         delete *listIter;
  530.     }
  531.     m_ListenSocketList.clear();
  532.  
  533.     m_bQuit = TRUE;
  534.  
  535.     if (!m_ThreadArray.size() && !m_ClosedThreads.size())
  536.     {
  537.         hMainWnd = 0;
  538.         DestroyWindow(m_hWnd);
  539.         m_hWnd = 0;
  540.         return;
  541.     }
  542.  
  543.     std::list<CServerThread *>::iterator iter;
  544.     for (iter = m_ThreadArray.begin(); iter != m_ThreadArray.end(); iter++)
  545.     {
  546.         VERIFY((*iter)->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, 0));
  547.     }
  548.     for (iter = m_ClosedThreads.begin(); iter != m_ClosedThreads.end(); iter++)
  549.     {
  550.         VERIFY((*iter)->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, 0));
  551.     }
  552. }
  553.  
  554. BOOL CServer::ProcessCommand(CAdminSocket *pAdminSocket, int nID, unsigned char *pData, int nDataLength)
  555. {
  556.     switch (nID)
  557.     {
  558.     case 2:
  559.         if (!nDataLength)
  560.         {
  561.             unsigned char buffer[2];
  562.             buffer[0] = m_nServerState / 256;
  563.             buffer[1] = m_nServerState % 256;
  564.             pAdminSocket->SendCommand(1, 2, buffer, 2);
  565.         }
  566.         else if (nDataLength == 2)
  567.         {
  568.             ToggleActive(*pData * 256 + pData[1]);
  569.             unsigned char buffer[2];
  570.             buffer[0] = m_nServerState / 256;
  571.             buffer[1] = m_nServerState % 256;
  572.             pAdminSocket->SendCommand(1, 2, buffer, 2);
  573.         }
  574.         else
  575.             pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length") + 1);
  576.         break;
  577.     case 3:
  578.         if (!nDataLength)
  579.             pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length") + 1);
  580.         else if (*pData == USERCONTROL_GETLIST)
  581.         {
  582.             int len = 3;
  583.             std::map<int, t_connectiondata>::iterator iter;
  584.             for (iter = m_UsersList.begin(); iter != m_UsersList.end(); iter++)
  585.             {
  586.                 const t_connectiondata& data = iter->second;
  587.                 char* ip = ConvToNetwork(data.ip);
  588.                 char* user = ConvToNetwork(data.user);
  589.                 len += 4 + (ip ? strlen(ip) : 0) + 2 + 4 + (user ? strlen(user) : 0) + 2 + 
  590.                        1;
  591.                 delete [] ip;
  592.                 delete [] user;
  593.                 if (data.transferMode)
  594.                 {
  595.                     char* physicalFile = ConvToNetwork(data.physicalFile);
  596.                     char* logicalFile = ConvToNetwork(data.logicalFile);
  597.                     len += 2 + (physicalFile ? strlen(physicalFile) : 0) + 2 + (logicalFile ? strlen(logicalFile) : 0);
  598.                     delete [] physicalFile;
  599.                     delete [] logicalFile;
  600.  
  601.                     if (data.currentOffset != 0)
  602.                         len += 8;
  603.                     if (data.totalSize != -1)
  604.                         len += 8;
  605.                 }
  606.             }
  607.             unsigned char *buffer = new unsigned char[len];
  608.             buffer[0] = USERCONTROL_GETLIST;
  609.             buffer[1] = m_UsersList.size() / 256;
  610.             buffer[2] = m_UsersList.size() % 256;
  611.             unsigned char *p = buffer + 3;
  612.             for (iter = m_UsersList.begin(); iter != m_UsersList.end(); iter++)
  613.             {
  614.                 const t_connectiondata& data = iter->second;
  615.                 char* ip = ConvToNetwork(data.ip);
  616.                 char* user = ConvToNetwork(data.user);
  617.                 int ipLen = ip ? strlen(ip) : 0;
  618.                 int userLen = user ? strlen(user) : 0;
  619.  
  620.                 memcpy(p, &data.userid, 4);
  621.                 p+=4;
  622.                 *p++ = ipLen / 256;
  623.                 *p++ = ipLen % 256;
  624.                 if (ip)
  625.                 {
  626.                     memcpy(p, ip, ipLen);
  627.                     p += ipLen;
  628.                     delete [] ip;
  629.                 }
  630.  
  631.                 memcpy(p, &data.port, 4);
  632.                 p += 4;
  633.  
  634.                 *p++ = userLen / 256;
  635.                 *p++ = userLen % 256;
  636.                 if (user)
  637.                 {
  638.                     memcpy(p, user, userLen);
  639.                     p += userLen;
  640.                     delete [] user;
  641.                 }
  642.  
  643.                 *p = data.transferMode;
  644.                 if (data.transferMode)
  645.                 {
  646.                     // Bit 5 and 6 indicate presence of currentOffset and totalSize.
  647.                     if (data.currentOffset != 0)
  648.                         *p |= 0x20;
  649.                     if (data.totalSize != -1)
  650.                         *p |= 0x40;
  651.                     p++;
  652.  
  653.                     char* physicalFile = ConvToNetwork(data.physicalFile);
  654.                     if (physicalFile)
  655.                     {
  656.                         int physicalLen = strlen(physicalFile);
  657.                         *p++ = physicalLen / 256;
  658.                         *p++ = physicalLen % 256;
  659.                         memcpy(p, physicalFile, physicalLen);
  660.                         delete [] physicalFile;
  661.                         p += physicalLen;
  662.                     }
  663.                     else
  664.                     {
  665.                         *p++ = 0;
  666.                         *p++ = 0;
  667.                     }
  668.  
  669.                     
  670.                     char* logicalFile = ConvToNetwork(data.logicalFile);
  671.                     if (logicalFile)
  672.                     {
  673.                         int logicalLen = strlen(logicalFile);
  674.                         *p++ = logicalLen / 256;
  675.                         *p++ = logicalLen % 256;
  676.                         memcpy(p, logicalFile, logicalLen);
  677.                         delete [] logicalFile;
  678.                         p += logicalLen;
  679.                     }
  680.                     else
  681.                     {
  682.                         *p++ = 0;
  683.                         *p++ = 0;
  684.                     }
  685.  
  686.                     if (data.currentOffset != 0)
  687.                     {
  688.                         memcpy(p, &data.currentOffset, 8);
  689.                         p += 8;
  690.                     }
  691.                     if (data.totalSize != -1)
  692.                     {
  693.                         memcpy(p, &data.totalSize, 8);
  694.                         p += 8;
  695.                     }
  696.                 }
  697.                 else
  698.                     p++;
  699.             }
  700.             m_pAdminInterface->SendCommand(1, 3, buffer, len);            
  701.             delete [] buffer;
  702.         }
  703.         else if (*pData == USERCONTROL_KICK || *pData == USERCONTROL_BAN)
  704.         {
  705.             if (nDataLength != 5)
  706.                 pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length")+1);
  707.             else
  708.             {
  709.                 int nUserID;
  710.                 memcpy(&nUserID, pData+1, 4);
  711.                 
  712.                 std::map<int, t_connectiondata>::iterator iter = m_UsersList.find(nUserID);
  713.                 if (iter!=m_UsersList.end())
  714.                 {
  715.                     if (*pData == USERCONTROL_BAN)
  716.                     {
  717.                         // Get the list of IP filter rules.
  718.                         CStdString ips = m_pOptions->GetOption(OPTION_IPFILTER_DISALLOWED);
  719.                         if (ips != _T(""))
  720.                             ips += _T(" ");
  721.  
  722.                         USES_CONVERSION;
  723.  
  724.                         int pos = ips.Find(' ');
  725.                         while (pos != -1)
  726.                         {
  727.                             CStdString blockedIP = ips.Left(pos);
  728.                             ips = ips.Mid(pos + 1);
  729.                             pos = ips.Find(' ');
  730.  
  731.                             if (MatchesFilter(blockedIP, iter->second.ip))
  732.                                 break;
  733.                         }
  734.                         if (pos == -1)
  735.                         {
  736.                             ips = m_pOptions->GetOption(OPTION_IPFILTER_DISALLOWED);
  737.                             if (ips != _T(""))
  738.                                 ips += _T(" ");
  739.                             ips += iter->second.ip;
  740.                             m_pOptions->SetOption(OPTION_IPFILTER_DISALLOWED, ips);
  741.                         }
  742.                     }    
  743.                     t_controlmessage *msg=new t_controlmessage;
  744.                     msg->command=USERCONTROL_KICK;
  745.                     msg->socketid=nUserID;
  746.                     iter->second.pThread->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_CONTROL, (LPARAM)msg);
  747.                     char buffer[2];
  748.                     buffer[0] = *pData;
  749.                     buffer[1] = 0;
  750.                     pAdminSocket->SendCommand(1, 3, &buffer, 2);
  751.                 }
  752.                 else
  753.                 {
  754.                     char buffer[2];
  755.                     buffer[0] = USERCONTROL_KICK;
  756.                     buffer[1] = 1;
  757.                     pAdminSocket->SendCommand(1, 3, &buffer, 2);
  758.                 }
  759.             }
  760.         }
  761.         else
  762.             pAdminSocket->SendCommand(1, 1, "\001Protocol error: Invalid data", strlen("\001Protocol error: Invalid data")+1);
  763.         break;
  764.     case 5:
  765.         if (!nDataLength)
  766.         {
  767.             char *pBuffer = NULL;
  768.             DWORD nBufferLength = 0;
  769.             if (m_pOptions && m_pOptions->GetAsCommand(&pBuffer, &nBufferLength))
  770.             {
  771.                 pAdminSocket->SendCommand(1, 5, pBuffer, nBufferLength);
  772.                 delete [] pBuffer;
  773.             }
  774.         }
  775.         else if (m_pOptions)
  776.         {
  777.             if (nDataLength < 2)
  778.                 pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length")+1);
  779.             else
  780.             {
  781.                 CStdString listenPorts = m_pOptions->GetOption(OPTION_SERVERPORT);
  782.                 CStdString listenPortsSsl = m_pOptions->GetOption(OPTION_SSLPORTS);
  783.                 bool enableSsl = m_pOptions->GetOptionVal(OPTION_ENABLESSL) != 0;
  784.                 int nAdminListenPort = (int)m_pOptions->GetOptionVal(OPTION_ADMINPORT);
  785.                 CStdString adminIpBindings = m_pOptions->GetOption(OPTION_ADMINIPBINDINGS);
  786.                 
  787.                 CStdString peerIP;
  788.                 UINT port = 0;
  789.                 bool bLocal = false;
  790.                 if (!pAdminSocket->GetPeerName(peerIP, port))
  791.                     return FALSE;
  792.                 else
  793.                     bLocal = IsLocalhost(peerIP);
  794.  
  795.                 if (!m_pOptions->ParseOptionsCommand(pData, nDataLength, bLocal))
  796.                 {
  797.                     pAdminSocket->SendCommand(1, 1, "\001Protocol error: Invalid data, could not import settings.", strlen("\001Protocol error: Invalid data, could not import settings.")+1);
  798.                     char buffer = 1;
  799.                     pAdminSocket->SendCommand(1, 5, &buffer, 1);
  800.                     break;
  801.                 }
  802.  
  803.                 char buffer = 0;
  804.                 pAdminSocket->SendCommand(1, 5, &buffer, 1);
  805.  
  806.                 unsigned int threadnum = (int)m_pOptions->GetOptionVal(OPTION_THREADNUM);
  807.                 if (m_nServerState & STATE_ONLINE)
  808.                 {
  809.                     if (threadnum > m_ThreadArray.size())
  810.                     {
  811.                         int newthreads = threadnum - m_ThreadArray.size();
  812.                         for (int i = 0; i < newthreads; i++)
  813.                         {
  814.                             int index = GetNextThreadNotificationID();
  815.                             CServerThread *pThread = new CServerThread(WM_FILEZILLA_SERVERMSG + index);
  816.                             m_ThreadNotificationIDs[index] = pThread;
  817.                             if (pThread->Create(THREAD_PRIORITY_NORMAL, CREATE_SUSPENDED))
  818.                             {
  819.                                 pThread->ResumeThread();
  820.                                 m_ThreadArray.push_back(pThread);
  821.                             }
  822.                         }
  823.                         CStdString str;
  824.                         str.Format(_T("Number of threads increased to %d."), threadnum);
  825.                         ShowStatus(str, 0);
  826.                     }
  827.                     else if (threadnum < m_ThreadArray.size())
  828.                     {
  829.                         CStdString str;
  830.                         str.Format(_T("Decreasing number of threads to %d."), threadnum);
  831.                         ShowStatus(str, 0);
  832.                         unsigned int i=0;
  833.                         std::list<CServerThread *> newList;
  834.                         for (std::list<CServerThread *>::iterator iter=m_ThreadArray.begin(); iter!=m_ThreadArray.end(); iter++,i++)
  835.                             if (i>=threadnum)
  836.                             {
  837.                                 (*iter)->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, 2);
  838.                                 m_ClosedThreads.push_back(*iter);
  839.                             }
  840.                             else
  841.                                 newList.push_back(*iter);
  842.                         m_ThreadArray.clear();
  843.                         m_ThreadArray = newList;
  844.                     }
  845.                 }
  846.                 if (listenPorts != m_pOptions->GetOption(OPTION_SERVERPORT) ||
  847.                     enableSsl != (m_pOptions->GetOptionVal(OPTION_ENABLESSL) != 0) ||
  848.                     (m_pOptions->GetOptionVal(OPTION_ENABLESSL) && listenPortsSsl != m_pOptions->GetOption(OPTION_SSLPORTS)))
  849.                 {
  850.                     if (!m_ListenSocketList.empty())
  851.                     {
  852.                         ShowStatus(_T("Closing all listening sockets"), 0);
  853.                         for (std::list<CListenSocket*>::iterator listIter = m_ListenSocketList.begin(); listIter != m_ListenSocketList.end(); listIter++)
  854.                         {
  855.                             (*listIter)->Close();
  856.                             delete *listIter;
  857.                         }
  858.                         m_ListenSocketList.clear();
  859.  
  860.                         if (!CreateListenSocket())
  861.                         {
  862.                             ShowStatus(_T("Failed to create a listen socket on any of the specified ports. Server is not online!"), 1);
  863.                             m_nServerState &= ~STATE_ONLINE;
  864.                         }
  865.                         else
  866.                         {
  867.                             ShowStatus(_T("Listen socket port changed"), 0);
  868.                             if (!(m_nServerState & STATE_MASK_GOOFFLINE))
  869.                                 m_nServerState |= STATE_ONLINE;
  870.                         }
  871.                         SendState();
  872.                     }
  873.                 }
  874.                 if (nAdminListenPort != m_pOptions->GetOptionVal(OPTION_ADMINPORT) || adminIpBindings!=m_pOptions->GetOption(OPTION_ADMINIPBINDINGS))
  875.                 {
  876.                     if (nAdminListenPort == m_pOptions->GetOptionVal(OPTION_ADMINPORT))
  877.                     {
  878.                         for (std::list<CAdminListenSocket*>::iterator iter = m_AdminListenSocketList.begin(); iter!=m_AdminListenSocketList.end(); iter++)
  879.                         {
  880.                             (*iter)->Close();
  881.                             delete *iter;
  882.                         }
  883.                         m_AdminListenSocketList.clear();
  884.                     }
  885.                     CAdminListenSocket *pSocket = new CAdminListenSocket(m_pAdminInterface);
  886.                     if (!pSocket->Create((int)m_pOptions->GetOptionVal(OPTION_ADMINPORT), SOCK_STREAM, FD_ACCEPT, (m_pOptions->GetOption(OPTION_ADMINIPBINDINGS) != _T("*")) ? _T("127.0.0.1") : NULL))
  887.                     {
  888.                         delete pSocket;
  889.                         CStdString str;
  890.                         str.Format(_T("Failed to change admin listen port to %I64d."), m_pOptions->GetOptionVal(OPTION_ADMINPORT));
  891.                         m_pOptions->SetOption(OPTION_ADMINPORT, nAdminListenPort);
  892.                         ShowStatus(str, 1);
  893.                     }
  894.                     else
  895.                     {
  896.                         pSocket->Listen();
  897.                         for (std::list<CAdminListenSocket*>::iterator iter = m_AdminListenSocketList.begin(); iter!=m_AdminListenSocketList.end(); iter++)
  898.                         {
  899.                             (*iter)->Close();
  900.                             delete *iter;
  901.                         }
  902.                         m_AdminListenSocketList.clear();
  903.  
  904.                         m_AdminListenSocketList.push_back(pSocket);
  905.                         if (nAdminListenPort != m_pOptions->GetOptionVal(OPTION_ADMINPORT))
  906.                         {
  907.                             CStdString str;
  908.                             str.Format(_T("Admin listen port changed to %I64d."), m_pOptions->GetOptionVal(OPTION_ADMINPORT));
  909.                             ShowStatus(str, 0);
  910.                         }
  911.  
  912.                         if (m_pOptions->GetOption(OPTION_ADMINIPBINDINGS) != _T("*"))
  913.                         {
  914.                             BOOL bError = FALSE;
  915.                             CStdString str = _T("Failed to bind the admin interface to the following IPs:");
  916.                             CStdString ipBindings = m_pOptions->GetOption(OPTION_ADMINIPBINDINGS);
  917.  
  918.                             if (ipBindings != _T(""))
  919.                                 ipBindings += _T(" ");
  920.                             while (ipBindings != _T(""))
  921.                             {
  922.                                 int pos = ipBindings.Find(' ');
  923.                                 if (pos == -1)
  924.                                     break;
  925.                                 CStdString ip = ipBindings.Left(pos);
  926.                                 ipBindings = ipBindings.Mid(pos+1);
  927.                                 CAdminListenSocket *pAdminListenSocket = new CAdminListenSocket(m_pAdminInterface);
  928.  
  929.                                 int family;
  930.                                 if (ip.Find(':') != -1)
  931.                                     family = AF_INET6;
  932.                                 else
  933.                                     family = AF_INET;
  934.  
  935.                                 if (!pAdminListenSocket->Create((int)m_pOptions->GetOptionVal(OPTION_ADMINPORT), SOCK_STREAM, FD_ACCEPT, ip, family) || !pAdminListenSocket->Listen())
  936.                                 {
  937.                                     bError = TRUE;
  938.                                     str += _T(" ") + ip;
  939.                                     delete pAdminListenSocket;
  940.                                 }
  941.                                 else
  942.                                     m_AdminListenSocketList.push_back(pAdminListenSocket);
  943.                             }
  944.                             if (bError)
  945.                                 ShowStatus(str, 1);
  946.                         }
  947.                         if (adminIpBindings != m_pOptions->GetOption(OPTION_ADMINIPBINDINGS))
  948.                             ShowStatus(_T("Admin interface IP bindings changed"), 0);
  949.                     }
  950.     
  951.                 }
  952.             }
  953.         }
  954.         break;
  955.     case 6:
  956.         if (!nDataLength)
  957.         {
  958.             char *pBuffer = NULL;
  959.             DWORD nBufferLength = 0;
  960.             CPermissions permissions;
  961.             permissions.GetAsCommand(&pBuffer, &nBufferLength);
  962.             pAdminSocket->SendCommand(1, 6, pBuffer, nBufferLength);
  963.             delete [] pBuffer;
  964.         }
  965.         else
  966.         {
  967.             if (nDataLength < 2)
  968.                 pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length")+1);
  969.             else
  970.             {
  971.                 CPermissions permissions;
  972.                 if (!permissions.ParseUsersCommand(pData, nDataLength))
  973.                 {
  974.                     pAdminSocket->SendCommand(1, 1, "\001Protocol error: Invalid data, could not import account settings.", strlen("\001Protocol error: Invalid data, could not import account settings.")+1);
  975.                     char buffer = 1;
  976.                     pAdminSocket->SendCommand(1, 6, &buffer, 1);
  977.                     break;
  978.                 }
  979.                 char buffer = 0;
  980.                 pAdminSocket->SendCommand(1, 6, &buffer, 1);
  981.             }
  982.         }
  983.         break;
  984.     case 8:
  985.         pAdminSocket->SendCommand(1, 8, NULL, 0);
  986.         break;
  987.     default:
  988.         {
  989.             CStdStringA str;
  990.             str.Format("\001Protocol error: Unknown command (%d).", nID);
  991.             pAdminSocket->SendCommand(1, 1, str.c_str(), str.GetLength());
  992.         }
  993.         break;
  994.     }
  995.  
  996.     return TRUE;
  997. }
  998.  
  999. BOOL CServer::ToggleActive(int nServerState)
  1000. {
  1001.     if (nServerState & STATE_GOOFFLINE_NOW)
  1002.     {
  1003.         if (m_nServerState & STATE_MASK_GOOFFLINE)
  1004.             return FALSE;
  1005.  
  1006.         for (std::list<CListenSocket*>::iterator listenIter = m_ListenSocketList.begin(); listenIter != m_ListenSocketList.end(); listenIter++)
  1007.         {
  1008.             (*listenIter)->Close();
  1009.             delete *listenIter;
  1010.         }
  1011.         m_ListenSocketList.clear();
  1012.         for (std::list<CServerThread *>::iterator iter = m_ClosedThreads.begin(); iter != m_ClosedThreads.end(); iter++)
  1013.             (*iter)->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, 0);
  1014.         for (std::list<CServerThread *>::iterator iter = m_ThreadArray.begin(); iter != m_ThreadArray.end(); iter++)
  1015.         {
  1016.             (*iter)->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, 0);
  1017.             m_ClosedThreads.push_back(*iter);
  1018.         }
  1019.         m_ThreadArray.clear();
  1020.         m_nServerState &= ~STATE_ONLINE;
  1021.         if (!m_ClosedThreads.empty())
  1022.             m_nServerState |= STATE_GOOFFLINE_NOW;
  1023.     }
  1024.     else if (nServerState & STATE_GOOFFLINE_LOGOUT)
  1025.     {
  1026.         if (m_nServerState & STATE_MASK_GOOFFLINE)
  1027.             return FALSE;
  1028.  
  1029.         for (std::list<CListenSocket*>::iterator listenIter = m_ListenSocketList.begin(); listenIter != m_ListenSocketList.end(); listenIter++)
  1030.         {
  1031.             (*listenIter)->Close();
  1032.             delete *listenIter;
  1033.         }
  1034.         m_ListenSocketList.clear();
  1035.         for (std::list<CServerThread *>::iterator iter = m_ClosedThreads.begin(); iter != m_ClosedThreads.end(); iter++)
  1036.             (*iter)->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, 2);
  1037.         for (std::list<CServerThread *>::iterator iter=m_ThreadArray.begin(); iter!=m_ThreadArray.end(); iter++)
  1038.         {
  1039.             (*iter)->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, 2);            
  1040.             m_ClosedThreads.push_back(*iter);
  1041.         }
  1042.         m_ThreadArray.clear();
  1043.         m_nServerState &= ~STATE_ONLINE;
  1044.         if (!m_ClosedThreads.empty())
  1045.             m_nServerState = m_nServerState |= STATE_GOOFFLINE_LOGOUT;
  1046.     }
  1047.     else if (nServerState & STATE_GOOFFLINE_WAITTRANSFER)
  1048.     {
  1049.         if (m_nServerState & STATE_MASK_GOOFFLINE)
  1050.             return FALSE;
  1051.  
  1052.         for (std::list<CListenSocket*>::iterator listenIter = m_ListenSocketList.begin(); listenIter != m_ListenSocketList.end(); listenIter++)
  1053.         {
  1054.             (*listenIter)->Close();
  1055.             delete *listenIter;
  1056.         }
  1057.         m_ListenSocketList.clear();
  1058.         for (std::list<CServerThread *>::iterator iter = m_ClosedThreads.begin(); iter != m_ClosedThreads.end(); iter++)
  1059.             (*iter)->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, 1);
  1060.         for (std::list<CServerThread *>::iterator iter=m_ThreadArray.begin(); iter!=m_ThreadArray.end(); iter++)
  1061.         {
  1062.             (*iter)->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, 1);            
  1063.             m_ClosedThreads.push_back(*iter);
  1064.         }
  1065.         m_ThreadArray.clear();
  1066.         m_nServerState &= ~STATE_ONLINE;
  1067.         if (!m_ClosedThreads.empty())
  1068.             m_nServerState = m_nServerState |= STATE_GOOFFLINE_WAITTRANSFER;
  1069.     }
  1070.     else if (nServerState & STATE_ONLINE)
  1071.     {
  1072.         if (m_ListenSocketList.empty())
  1073.         {
  1074.             if (!CreateListenSocket())
  1075.             {
  1076.                 ShowStatus(_T("Failed to create a listen socket on any of the specified ports. Server is not online!"), 1);
  1077.                 return true;
  1078.             }
  1079.         }
  1080.  
  1081.         if (!m_ListenSocketList.empty())
  1082.         {
  1083.             ShowStatus(_T("Server online"), 0);
  1084.             int i = 0;
  1085.             int num = (m_pOptions ? (int)m_pOptions->GetOptionVal(OPTION_THREADNUM) : 2);
  1086.  
  1087.             //Recreate the threads
  1088.             for (i = m_ThreadArray.size(); i < num; i++)
  1089.             {
  1090.                 int index = GetNextThreadNotificationID();
  1091.                 CServerThread *pThread = new CServerThread(WM_FILEZILLA_SERVERMSG + index);
  1092.                 m_ThreadNotificationIDs[index] = pThread;
  1093.                 if (pThread->Create(THREAD_PRIORITY_NORMAL, CREATE_SUSPENDED))
  1094.                 {
  1095.                     m_ThreadArray.push_back(pThread);
  1096.                     pThread->ResumeThread();
  1097.                 }
  1098.             }
  1099.         }
  1100.         for (std::list<CListenSocket *>::iterator iter = m_ListenSocketList.begin(); iter != m_ListenSocketList.end(); iter++)
  1101.             (*iter)->m_bLocked = nServerState & STATE_LOCKED;
  1102.  
  1103.         // Set closing threads to "wait until logout" mode.
  1104.         for (std::list<CServerThread *>::iterator iter = m_ClosedThreads.begin(); iter != m_ClosedThreads.end(); iter++)
  1105.             (*iter)->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, 2);
  1106.  
  1107.         m_nServerState = (m_ListenSocketList.empty() ? 0 : STATE_ONLINE) + (nServerState & STATE_LOCKED);
  1108.     }
  1109.  
  1110.     SendState();
  1111.     return TRUE;
  1112. }
  1113.  
  1114. void CServer::ShowStatus(LPCTSTR msg, int nType)
  1115. {
  1116.     char* utf8 = ConvToNetwork(msg);
  1117.     if (!utf8)
  1118.         return;
  1119.  
  1120.     char *pBuffer = new char[strlen(utf8) + 1];
  1121.     *pBuffer = nType;
  1122.     memcpy(pBuffer + 1, utf8, strlen(utf8));
  1123.     if (m_pAdminInterface)
  1124.         m_pAdminInterface->SendCommand(2, 1, pBuffer, strlen(utf8) + 1);
  1125.     delete [] pBuffer;
  1126.     delete [] utf8;
  1127.  
  1128.     if (m_pFileLogger)
  1129.         m_pFileLogger->Log(msg);
  1130. }
  1131.  
  1132. void CServer::ShowStatus(DWORD eventDateHigh, DWORD eventDateLow, LPCTSTR msg, int nType)
  1133. {
  1134.     char* utf8 = ConvToNetwork(msg);
  1135.     if (!utf8)
  1136.         return;
  1137.     if (!*utf8)
  1138.     {
  1139.         delete [] utf8;
  1140.         return;
  1141.     }
  1142.  
  1143.     unsigned int utf8len = strlen(utf8);
  1144.     char *pBuffer = new char[utf8len + 1 + 8];
  1145.     *pBuffer = nType;
  1146.     memcpy(pBuffer + 1, &eventDateHigh, 8);
  1147.     memcpy(pBuffer + 5, &eventDateLow, 4);
  1148.     memcpy(pBuffer + 1 + 8, utf8, utf8len);
  1149.     if (m_pAdminInterface)
  1150.         m_pAdminInterface->SendCommand(2, 4, pBuffer, utf8len + 1 + 8);
  1151.     delete [] pBuffer;
  1152.     delete [] utf8;
  1153.  
  1154.     //Log string
  1155.     if (m_pFileLogger)
  1156.     {
  1157.         FILETIME fFileTime;
  1158.         SYSTEMTIME sFileTime;
  1159.         fFileTime.dwHighDateTime = eventDateHigh;
  1160.         fFileTime.dwLowDateTime = eventDateLow;
  1161.         FileTimeToSystemTime(&fFileTime, &sFileTime);
  1162.         TCHAR text[80];
  1163.         if (!GetDateFormat(
  1164.             LOCALE_USER_DEFAULT,               // locale for which date is to be formatted
  1165.             DATE_SHORTDATE,             // flags specifying function options
  1166.             &sFileTime,  // date to be formatted
  1167.             0,          // date format string
  1168.             text,          // buffer for storing formatted string
  1169.             80                // size of buffer
  1170.             ))
  1171.             return;
  1172.         
  1173.         CStdString text2 = _T(" ");
  1174.         text2 += text;
  1175.         
  1176.         if (!GetTimeFormat(
  1177.             LOCALE_USER_DEFAULT,               // locale for which date is to be formatted
  1178.             TIME_FORCE24HOURFORMAT,             // flags specifying function options
  1179.             &sFileTime,  // date to be formatted
  1180.             0,          // date format string
  1181.             text,          // buffer for storing formatted string
  1182.             80                // size of buffer
  1183.             ))
  1184.             return;
  1185.  
  1186.         text2 += _T(" ");
  1187.         text2 += text;
  1188.         CStdString str = msg;
  1189.         int pos = str.Find(_T("-"));
  1190.         if (pos!=-1)
  1191.         {
  1192.             str.Insert(pos, text2 + _T(" "));
  1193.         }
  1194.         m_pFileLogger->Log(str);
  1195.     }
  1196. }
  1197.  
  1198. void CServer::OnTimer(UINT nIDEvent)
  1199. {
  1200.     if (nIDEvent == m_nBanTimerID)
  1201.     {
  1202.         if (m_pAutoBanManager)
  1203.             m_pAutoBanManager->PurgeOutdated();
  1204.         return;
  1205.     }
  1206.  
  1207.     m_pAdminInterface->CheckForTimeout();
  1208.     m_pFileLogger->CheckLogFile();
  1209. }
  1210.  
  1211. int CServer::DoCreateAdminListenSocket(UINT port, LPCTSTR addr, int family)
  1212. {
  1213.     CAdminListenSocket *pAdminListenSocket = new CAdminListenSocket(m_pAdminInterface);
  1214.     if (!pAdminListenSocket->Create(port, SOCK_STREAM, FD_ACCEPT, addr, family))
  1215.     {
  1216.         delete pAdminListenSocket;
  1217.         return 0;
  1218.     }
  1219.  
  1220.     if (!pAdminListenSocket->Listen())
  1221.     {
  1222.         delete pAdminListenSocket;
  1223.         return 0;
  1224.     }
  1225.  
  1226.     if (!port)
  1227.     {
  1228.         CStdString ip;
  1229.         BOOL bResult = pAdminListenSocket->GetSockName(ip, port);
  1230.         if (!bResult)
  1231.         {
  1232.             delete pAdminListenSocket;
  1233.             return 0;
  1234.         }
  1235.     }
  1236.     
  1237.     m_AdminListenSocketList.push_back(pAdminListenSocket);
  1238.     return port;
  1239. }
  1240.  
  1241. BOOL CServer::CreateAdminListenSocket()
  1242. {
  1243.     CStdString ipBindings = (m_pOptions ? m_pOptions->GetOption(OPTION_ADMINIPBINDINGS) : _T(""));
  1244.     int nAdminPort = (m_pOptions ? (int)m_pOptions->GetOptionVal(OPTION_ADMINPORT) : 14147);
  1245.  
  1246.     CStdString error;
  1247.  
  1248.     if (!DoCreateAdminListenSocket(nAdminPort, (ipBindings != _T("*")) ? _T("127.0.0.1") : NULL, AF_INET))
  1249.     {
  1250.         int p = DoCreateAdminListenSocket(nAdminPort, _T("127.0.0.1"), AF_INET);
  1251.         if (!p)
  1252.         {
  1253.             CStdString str;
  1254.             str.Format(_T("Failed to create listen socket for admin interface on port %d for IPv4, the IPv4 admin interface has been disabled."), nAdminPort);
  1255.             ShowStatus(str, 1);
  1256.             error += _T("\n") + str;
  1257.         }
  1258.         else
  1259.         {
  1260.             CStdString str;
  1261.             str.Format(_T("Failed to create listen socket for admin interface on port %d for IPv4, for this session the IPv4 admin interface is available on port %u."), p);
  1262.             ShowStatus(str, 1);
  1263.             error += _T("\n") + str;
  1264.         }
  1265.     }
  1266.  
  1267.     if (!m_pOptions->GetOptionVal(OPTION_DISABLE_IPV6))
  1268.     {
  1269.         if (!DoCreateAdminListenSocket(nAdminPort, (ipBindings != _T("*")) ? _T("::1") : NULL, AF_INET6))
  1270.         {
  1271.             int p = DoCreateAdminListenSocket(nAdminPort, _T("127.0.0.1"), AF_INET6);
  1272.             if (!p)
  1273.             {
  1274.                 CStdString str;
  1275.                 str.Format(_T("Failed to create listen socket for admin interface on port %d for IPv6, the IPv6 admin interface has been disabled."), nAdminPort);
  1276.                 ShowStatus(str, 1);
  1277.                 error += _T("\n") + str;
  1278.             }
  1279.             else
  1280.             {
  1281.                 CStdString str;
  1282.                 str.Format(_T("Failed to create listen socket for admin interface on port %d for IPv6, for this session the IPv6 admin interface is available on port %u."), p);
  1283.                 ShowStatus(str, 1);
  1284.                 error += _T("\n") + str;
  1285.             }
  1286.         }
  1287.     }
  1288.  
  1289.     if (ipBindings != _T("*"))
  1290.     {
  1291.         if (ipBindings != _T(""))
  1292.             ipBindings += _T(" ");
  1293.         while (ipBindings != _T(""))
  1294.         {
  1295.             int pos = ipBindings.Find(' ');
  1296.             if (pos == -1)
  1297.                 break;
  1298.             CStdString ip = ipBindings.Left(pos);
  1299.             ipBindings = ipBindings.Mid(pos+1);
  1300.             CAdminListenSocket *pAdminListenSocket = new CAdminListenSocket(m_pAdminInterface);
  1301.  
  1302.             int family;
  1303.             if (ip.Find(':') != -1)
  1304.                 family = AF_INET6;
  1305.             else
  1306.                 family = AF_INET;
  1307.  
  1308.             if (!pAdminListenSocket->Create(nAdminPort, SOCK_STREAM, FD_ACCEPT, ip, family) || !pAdminListenSocket->Listen())
  1309.             {
  1310.                 delete pAdminListenSocket;
  1311.                 error += _T("\n") + ip;
  1312.             }
  1313.             else
  1314.                 m_AdminListenSocketList.push_back(pAdminListenSocket);
  1315.         }
  1316.     }
  1317.  
  1318.     /* Disabled since appareantly MessageBox freezes the server on Windows Server 2003.
  1319.     if (!error.IsEmpty())
  1320.     {
  1321.         error = _T("Failed to bind the admin interface to the following addresses:") + error;
  1322.         MessageBox(0, error, _T("FileZilla Server Error"), MB_ICONEXCLAMATION | MB_SERVICE_NOTIFICATION);
  1323.     }*/
  1324.  
  1325.     return !m_AdminListenSocketList.empty();
  1326. }
  1327.  
  1328. BOOL CServer::CreateListenSocket()
  1329. {
  1330.     CStdString ports = (m_pOptions ? m_pOptions->GetOption(OPTION_SERVERPORT) : _T("21"));
  1331.     bool ssl = false;
  1332.     
  1333.     if (ports == _T("") && m_pOptions && m_pOptions->GetOptionVal(OPTION_ENABLESSL))
  1334.     {
  1335.         ports = m_pOptions->GetOption(OPTION_SSLPORTS);
  1336.         ssl = true;
  1337.     }
  1338.  
  1339.     if (ports == _T(""))
  1340.     {
  1341.         ShowStatus(_T("No listen ports set in settings"), 1);
  1342.         return false;
  1343.     }
  1344.  
  1345.     ports += _T(" ");
  1346.     int pos = ports.Find(' ');
  1347.     while (pos > 0)
  1348.     {
  1349.         CStdString ipBindings = (m_pOptions ? m_pOptions->GetOption(OPTION_IPBINDINGS) : _T("*"));
  1350.         if (ipBindings == _T(""))
  1351.             ipBindings = _T("*");
  1352.         int nPort = _ttoi(ports.Left(pos));
  1353.         ports = ports.Mid(pos + 1);
  1354.         pos = ports.Find(' ');
  1355.  
  1356.         CStdString str;
  1357.         str.Format(_T("Creating listen socket on port %d..."), nPort);
  1358.         ShowStatus(str, 0);
  1359.         if (ipBindings == _T("*"))
  1360.         {
  1361.             CListenSocket *pListenSocket = new CListenSocket(this, ssl);
  1362.             pListenSocket->m_pThreadList = &m_ThreadArray;
  1363.     
  1364.             if (!pListenSocket->Create(nPort, SOCK_STREAM, FD_ACCEPT, NULL, AF_INET) || !pListenSocket->Listen())
  1365.             {
  1366.                 delete pListenSocket;
  1367.                 pListenSocket = NULL;
  1368.                 str.Format(_T("Failed to create listen socket on port %d for IPv4"), nPort);
  1369.                 ShowStatus(str, 1);
  1370.             }
  1371.             else
  1372.                 m_ListenSocketList.push_back(pListenSocket);
  1373.  
  1374.             if (!m_pOptions->GetOptionVal(OPTION_DISABLE_IPV6))
  1375.             {
  1376.                 CListenSocket *pListenSocket = new CListenSocket(this, ssl);
  1377.                 pListenSocket->m_pThreadList = &m_ThreadArray;
  1378.         
  1379.                 if (!pListenSocket->Create(nPort, SOCK_STREAM, FD_ACCEPT, NULL, AF_INET6) || !pListenSocket->Listen())
  1380.                 {
  1381.                     delete pListenSocket;
  1382.                     pListenSocket = NULL;
  1383.                     str.Format(_T("Failed to create listen socket on port %d for IPv6"), nPort);
  1384.                     ShowStatus(str, 1);
  1385.                 }
  1386.                 else
  1387.                     m_ListenSocketList.push_back(pListenSocket);
  1388.             }
  1389.         }
  1390.         else
  1391.         {
  1392.             BOOL bError = FALSE;
  1393.             CStdString str;
  1394.             str.Format(_T("Failed to bind the listen socket on port %d to the following IPs:"), nPort);
  1395.             ipBindings += _T(" ");
  1396.             while (ipBindings != _T(""))
  1397.             {
  1398.                 int pos = ipBindings.Find(' ');
  1399.                 if (pos == -1)
  1400.                     break;
  1401.                 CStdString ip = ipBindings.Left(pos);
  1402.                 ipBindings = ipBindings.Mid(pos + 1);
  1403.                 CListenSocket *pListenSocket = new CListenSocket(this, ssl);
  1404.                 pListenSocket->m_pThreadList = &m_ThreadArray;
  1405.                 
  1406.                 int family;
  1407.                 if (ip.Find(':') != -1)
  1408.                     family = AF_INET6;
  1409.                 else
  1410.                     family = AF_INET;
  1411.  
  1412.                 if (!pListenSocket->Create(nPort, SOCK_STREAM, FD_ACCEPT, ip, family) || !pListenSocket->Listen())
  1413.                 {
  1414.                     delete pListenSocket;
  1415.                     bError = TRUE;
  1416.                     str += _T(" ") + ip;
  1417.                 }
  1418.                 else
  1419.                     m_ListenSocketList.push_back(pListenSocket);
  1420.             }
  1421.             if (bError)
  1422.                 ShowStatus(str, 1);
  1423.         }
  1424.  
  1425.         if (pos < 1 && !ssl && m_pOptions && m_pOptions->GetOptionVal(OPTION_ENABLESSL))
  1426.         {
  1427.             // Now create the ssl ports
  1428.             ports = m_pOptions->GetOption(OPTION_SSLPORTS);
  1429.             ports += _T(" ");
  1430.             pos = ports.Find(' ');
  1431.             ssl = true;
  1432.         }
  1433.     }
  1434.  
  1435.     return !m_ListenSocketList.empty();
  1436. }
  1437.  
  1438. unsigned int CServer::GetNextThreadNotificationID()
  1439. {
  1440.     for (unsigned int i = 0; i < m_ThreadNotificationIDs.size(); i++)
  1441.         if (!m_ThreadNotificationIDs[i])
  1442.             return i;
  1443.  
  1444.     m_ThreadNotificationIDs.push_back(0);
  1445.     return m_ThreadNotificationIDs.size() - 1;
  1446. }
  1447.  
  1448. void CServer::FreeThreadNotificationID(CServerThread *pThread)
  1449. {
  1450.     for (unsigned int i = 0; i < m_ThreadNotificationIDs.size(); i++)
  1451.         if (m_ThreadNotificationIDs[i] == pThread)
  1452.         {
  1453.             m_ThreadNotificationIDs[i] = 0;
  1454.             break;
  1455.         }
  1456.  
  1457. }
  1458.  
  1459. void CServer::SendState()
  1460. {
  1461.     if (!m_pAdminInterface)
  1462.         return;
  1463.  
  1464.     // Send state to interface
  1465.     unsigned char buffer[2];
  1466.     buffer[0] = m_nServerState / 256;
  1467.     buffer[1] = m_nServerState % 256;
  1468.     m_pAdminInterface->SendCommand(2, 2, buffer, 2);
  1469. }
  1470.